import type { AdjustElementStyleConfig } from '../../lib/abstract'
import type { ComponentStyleIdType } from '../../types/interfaces'
import type { StepItem } from '../step_bar/types'
import type {
  DataChangeType,
  DeleteLinePayload,
  EditType,
  selectedType,
  StyleEditorProps,
  StyleProperty,
} from './interfaces'
import { UIComponent } from '../../lib/abstract'
import { ToolKit } from '../../lib/utils/toolkit'
import {
  ComponentStyleId,
  CUSTOM_EVENTS,
  EDIT_TYPE_CONFIG,
  FOCUS_MODE_CONFIG,
  logger,
  TITLE_STYLES,
} from '../../types/constants'
import { StylesService } from '../../types/constants/styles'
import { SYMBOLS } from '../../types/interfaces'
import { StepBar } from '../step_bar'
import { EDIT_STEP_STATUS } from '../step_bar/types'
import { ToggleSwitch } from '../toggle_switch'
import { Toolbar } from '../toolbar'
import { ActionButtons } from './action_buttons'
import { QUICK_PRESETS } from './constants'
import { ElementStylePicker } from './element_style_picker'
import { MyFavorites } from './my_favorites'
import { PreviewConfig } from './preview_config'

interface ComponentRegistry {
  base: {
    focusModeToggle: ToggleSwitch
    editStep: StepBar
    toolbar: Toolbar
  }
  module: {
    elementStylePicker: ElementStylePicker
    myFavorites: MyFavorites
    actionButtons: ActionButtons
    previewConfig: PreviewConfig
  }
}
type ComponentCategory = keyof ComponentRegistry
type AllComponentNames = {
  [K in ComponentCategory]: keyof ComponentRegistry[K]
}[ComponentCategory]

export class StyleEditor extends UIComponent<StyleEditorProps> {
  id: string = 'style-editor'
  readonly description: string = '元素样式编辑器'
  readonly styleId: string = ComponentStyleId[this.name]
  private readonly components: ComponentRegistry
  private savedStyles: any[] = []
  private savedStylesStorageKey: string = 'savedStyles'
  private stylesConfig: AdjustElementStyleConfig[] = []
  private markedSelector = new Set<string>()
  private readonly focusModeToggleLabel = `${SYMBOLS.OTHERS.FOCUS} 专注模式`
  private stateMap = new WeakMap<Element, number>()

  get name(): ComponentStyleIdType {
    return 'StyleEditor'
  }

  get className(): string {
    return 'style-editor'
  }

  constructor(props: StyleEditorProps) {
    super(props)

    // 初始化所有组件
    this.components = this.initializeComponents()

    // 加载已保存的样式
    this.loadLatestStyles('cache')

    // 组件初始化后再注册样式
    this.registerStyles()
  }

  ELEMENT_SELECTORS = {
    focusModeToggle: { selector: '#focus-mode-toggle', dynamic: false, unique: true },
    editArea: { selector: '.edit-area', dynamic: false, unique: false },
    editPreview: { selector: '.edit-preview', dynamic: false, unique: false },
  }

  /**
   * 初始化所有子组件
   */
  private initializeComponents() {
    const steps: StepItem[] = [
      { title: '选择『页面元素』', subTitle: '' },
      { title: '选择『元素样式』', subTitle: '' },
      { title: '点击\'添加配置\'', subTitle: '' },
      { title: '生成配置', subTitle: '' },
    ]

    const menus = [
      {
        id: 'element-marking',
        icon: SYMBOLS.UI.SEARCH,
        text: '元素标记',
        children: [
          { id: 'mark-element', text: '标记元素', icon: SYMBOLS.UI.BOOKMARK, onClick: () => this.handleMarkClick() },
          { id: 'clear-marks', text: '清除标记', icon: SYMBOLS.OTHERS.CLEAR, onClick: () => this.handleClearMarkClick() },
        ],
      },
      {
        id: 'quick-presets',
        icon: SYMBOLS.WEATHER.LIGHTNING,
        text: '快捷设置',
        children: QUICK_PRESETS.map(preset => ({
          id: `preset-${preset.value.replace(/\s+/g, '-')}`,
          text: preset.label,
          icon: preset.icon || '',
          onClick: () => {
            this.handlePresetSelect(preset.value)
            this.eventEmitter.emit(CUSTOM_EVENTS.EDIT_STEP, EDIT_TYPE_CONFIG.QUICK)
          },
        })),
      },
    ]

    return {
      base: {
        focusModeToggle: new ToggleSwitch({
          id: 'focus-mode-toggle',
          checked: false,
          labelOn: this.focusModeToggleLabel,
          labelOff: this.focusModeToggleLabel,
          onChange: (checked: boolean) => {
            this.handleFocusModeToggle(checked)
          },
        }),
        editStep: new StepBar({
          steps,
        }),
        toolbar: new Toolbar({
          id: 'style-editor-toolbar',
          menus,
        }),
      },
      module: {
        elementStylePicker: new ElementStylePicker({
          onSelect: (element: selectedType, style: selectedType) =>
            this.handleElementStyleSelect(element, style),
        }),
        myFavorites: MyFavorites.getInstance(),
        actionButtons: new ActionButtons({
          onAdd: this.handleAddClick,
          onReset: this.handleClearClick,
        }),
        previewConfig: new PreviewConfig({
          onClickClearAll: () => {
            this.deleteStyles()
            this.loadLatestStyles('clear')

            if (!this.components.module.elementStylePicker.selectedElement) {
              this.handleEditStepStatus(EDIT_TYPE_CONFIG.SELECT_ELEMENT, true)
            }
            else {
              this.handleEditStepStatus(EDIT_TYPE_CONFIG.SELECT_STYLE, true)
            }
          },
          onClickDeleteLine: (lineNum: number, payload: DeleteLinePayload) => {
            this.handleClickDeleteLine(lineNum, payload)
          },
          onUpdated: (sourceType: DataChangeType) => {
            if (sourceType !== 'clear') {
              this.eventEmitter.emit(CUSTOM_EVENTS.EDIT_STEP, EDIT_TYPE_CONFIG.GENERATE)
            }
            this.props.onGenerated(this.readSavedStyles())
          },
        }),
      },
    }
  }

  render(): string {
    return `
      <div class="${this.className}">
        <div class="editor-menu">
          <div class="menu-left">
          </div>
          <div class="menu-right">
            <div class="focus-mode">${this.renderFocusMode()}</div>
          </div>
        </div>
        <div class="editor-step">
            ${this.renderEditStep()}
        </div>
        <div class="editor-selector">
        ${this.components.module.elementStylePicker.render()}
        </div>
        <div class="editor-content">
          <div class="edit-header ${TITLE_STYLES.SECONDARY.className}">
            <span class="icon">${SYMBOLS.STATUS.REFRESH}</span>
            <span class="title">开始调整</span>
          </div>
          <div class="edit-toolbar">
            ${this.components.base.toolbar.render()}
            ${this.components.module.myFavorites.render()}
          </div>
          <div class="edit-area">
            ${this.renderEditAreaSkeleton()}
          </div>
          <div class="edit-actions">
            ${this.components.module.actionButtons.render()}
          </div>
          <div class="edit-preview">
            ${this.components.module.previewConfig.render(this.savedStyles)}
          </div>
        </div>
      </div>
    `
  }

  /**
   * 渲染专注模式按钮
   */
  renderFocusMode(): string {
    return this.components.base.focusModeToggle.render()
  }

  /**
   * 渲染编辑步骤
   */
  renderEditStep(): string {
    return this.components.base.editStep.render()
  }

  /**
   * 编辑区域骨架屏
   */
  private renderEditAreaSkeleton(): string {
    return `
      <div class="edit-skeleton">
        <div class="skeleton-row">
          <div class="skeleton-label"></div>
          <div class="skeleton-input"></div>
        </div>
        <div class="skeleton-row">
          <div class="skeleton-label"></div>
          <div class="skeleton-input"></div>
        </div>
        <div class="skeleton-row">
          <div class="skeleton-label"></div>
          <div class="skeleton-input"></div>
        </div>
      </div>
    `
  }

  bindEvents(): void {
    // 挂载所有组件
    this.mountAllComponents()
    // 绑定事件
    this.eventEmitter.on(CUSTOM_EVENTS.EDIT_STEP, (type: EditType) => this.handleEditStepStatus(type))
  }

  mountAllComponents(): void {
    const priority: ComponentCategory[] = ['base', 'module']
    const skip: AllComponentNames[] = []

    // 按优先级顺序挂载组件
    priority.forEach((category) => {
      if (!this.components[category]) {
        logger.warn(`[${this.name}] 未知组件分类: ${category}`)
        return
      }

      logger.info(`[${this.name}] 开始挂载 ${category} 分类组件`, {
        category,
        componentCount: Object.keys(this.components[category]).length,
      })

      this.mountCategoryComponents(category, skip)
    })
  }

  /**
   * 挂载指定分类的组件
   * @private
   * @method mountCategoryComponents
   * @param category - 组件分类
   * @param skip - 需要跳过的组件名称
   */
  private mountCategoryComponents(
    category: ComponentCategory,
    skip: AllComponentNames[],
  ): void {
    Object.entries(this.components[category]).forEach(([name, component]) => {
      if (skip.includes(name as AllComponentNames)) {
        logger.warn(`[${this.name}] 跳过组件: ${category}.${name}`)
        return
      }

      try {
        component.mount(this.$element!)
        logger.info(`[${this.name}] 成功挂载组件: ${category}.${name}`)
      }
      catch (error: any) {
        logger.error(
          `[${this.name}] 挂载组件失败: ${category}.${name}`,
          error,
        )
      }
    })
  }

  /**
   * 处理专注模式切换
   */
  private handleFocusModeToggle(isFocusMode: boolean) {
    this.$element?.toggleClass('focus-mode', isFocusMode)

    // 切换前保存滚动位置
    if (isFocusMode) {
      this.saveScrollPositions()
    }

    // 处理所有配置元素
    this.toggleFocusModeElements(isFocusMode)

    // 恢复滚动位置
    if (!isFocusMode) {
      this.restoreScrollPositions()
    }
  }

  /**
   * 切换所有相关元素状态
   */
  private toggleFocusModeElements(isFocusMode: boolean) {
    Object.entries(FOCUS_MODE_CONFIG.elements).forEach(([_, config]) => {
      const elements = $(config.selector)

      if (config.action === 'toggle') {
        elements.toggle(!isFocusMode)
      }
      else if (config.action === 'display' && config.value) {
        ToolKit.dom.setElementCssAttribute(elements, isFocusMode ? config.value[0] : config.value[1])
      }

      if (config.styles) {
        Object.entries(config.styles).forEach(([prop, values]) => {
          elements[0].style.setProperty(prop, isFocusMode ? values[0] : values[1], 'important')
        })
      }
    })
  }

  /**
   * 保存滚动位置
   */
  private saveScrollPositions() {
    document.querySelectorAll('.user-center-modal .tab-content').forEach((el) => {
      this.stateMap.set(el, el.scrollTop)
    })
  }

  /**
   * 恢复滚动位置
   */
  private restoreScrollPositions() {
    document.querySelectorAll('.user-center-modal .tab-content').forEach((el) => {
      const pos = this.stateMap.get(el)
      if (pos !== undefined)
        el.scrollTop = pos
    })
  }

  /**
   * 处理添加按钮点击事件
   */
  private handleAddClick = () => {
    this.eventEmitter.emit(CUSTOM_EVENTS.EDIT_STEP, EDIT_TYPE_CONFIG.ADD)

    // 收集所有控件的值并存储
    this.stylesConfig = this.collectControlValues()

    // 加载最新样式
    this.loadLatestStyles('add', this.stylesConfig)
  }

  /**
   * 处理行删除点击事件
   */
  private handleClickDeleteLine(_lineNum: number, payload: DeleteLinePayload) {
    this.deleteStyleProperty(payload)
    this.loadLatestStyles('delete')
  }

  /**
   * 删除全部样式
   */
  deleteStyles(): void {
    this.storage.delete(this.savedStylesStorageKey)
  }

  /**
   * 删除指定样式属性
   */
  deleteStyleProperty(payload: DeleteLinePayload): void {
    // 1. 通过 id 反向查找原始选择器
    const selectorId = this.components.module.previewConfig.styleIdManager.getOriginalId(payload.id, payload.property)
    if (!selectorId) {
      logger.warn(`[${this.name}] 未找到 styleId ${payload.id} 对应的选择器，跳过删除`)
      return
    }

    // 2. 从存储中加载最新样式
    const savedStyles = this.storage.get(this.savedStylesStorageKey, [])

    // 3. 过滤出需要保留的样式
    const updatedStyles = savedStyles.filter((style: AdjustElementStyleConfig) =>
      !(style.id === selectorId && style.property === payload.property),
    )

    // 4. 更新存储并重新加载
    this.saveStyles(updatedStyles)
    this.loadLatestStyles('delete')

    // 5. 清理映射关系
    this.components.module.previewConfig.styleIdManager.clearMapping(payload.id)

    logger.info(`[${this.name}] 已删除选择器 ${selectorId} 的属性 ${payload.property}`)
  }

  /**
   * 保存样式
   */
  private saveStyles(data: any[]) {
    this.storage.set(this.savedStylesStorageKey, data)
  }

  /**
   * 读取已保存的样式
   */
  private readSavedStyles(): AdjustElementStyleConfig[] {
    return this.storage.get(this.savedStylesStorageKey, [])
  }

  /**
   * 处理重置按钮点击事件
   */
  private handleClearClick = () => {
    this.getElement('editArea')?.html(this.renderEditAreaSkeleton())
    // 启用样式选择器的强制渲染
    this.components.module.elementStylePicker.forceRenderStyleControls = true
    // 清空样式选择器列表
    this.components.module.elementStylePicker.controlInstances = {}
    // 重置元素样式及提示
    this.components.module.elementStylePicker.resetStyleSelectStatus()
  }

  /**
   * 处理标记按钮点击事件
   */
  private handleMarkClick = () => {
    const selector = this.components.module.elementStylePicker.getElementSelector()
    $(selector)?.css({
      border: '1px solid red',
    })
    this.markedSelector.add(selector)
  }

  /**
   * 处理清除标记按钮点击事件
   */
  private handleClearMarkClick = () => {
    this.markedSelector.forEach((selector) => {
      $(selector)?.css({
        border: 'none',
      })
      this.markedSelector.delete(selector)
    })
  }

  /**
   * 获取元素样式配置
   */
  private getElementStyleConfigBase(property: StyleProperty, value: string): AdjustElementStyleConfig {
    const selector = this.components.module.elementStylePicker.getElementSelector()

    if (!selector) {
      logger.warn(`[${this.name}] 未选择目标页面元素`)
    }

    return {
      id: this.components.module.elementStylePicker.selectedElement?.id || '',
      name: this.components.module.elementStylePicker.selectedElement?.name || '',
      category: this.components.module.elementStylePicker.selectedElement?.groupName || this.components.module.elementStylePicker.selectedElement?.group || '',
      selector,
      property,
      value,
      updateTime: Date.now(),
    }
  }

  /**
   * 收集所有控件的值
   */
  private collectControlValues(): AdjustElementStyleConfig[] {
    const styles: AdjustElementStyleConfig[] = []

    // 遍历所有控制组件实例
    Object.entries(this.components.module.elementStylePicker.controlInstances).forEach(([property, instances]) => {
      const values = instances.map(instance => instance.getValue())
      styles.push(this.getElementStyleConfigBase(property, values.join(' ')))
    })

    return styles
  }

  /**
   * 加载已保存的样式
   */
  private loadLatestStyles(source: DataChangeType, extraStyles?: AdjustElementStyleConfig[]) {
    // 读取已保存的样式
    const parsedStyles = this.readSavedStyles()

    // 清空全部时如果历史配置为空则跳过处理
    if (source === 'clear' && parsedStyles.length === 0)
      return

    // 合并额外样式并保存
    this.savedStyles = extraStyles && this.components.module.elementStylePicker.selectedElement
      ? this.mergeStyles(parsedStyles, extraStyles)
      : parsedStyles

    if (extraStyles)
      this.saveStyles(this.savedStyles)

    // 更新UI
    this.updatePreviewUI(source)
  }

  /**
   * 合并样式配置（去重逻辑）
   */
  private mergeStyles(
    base: AdjustElementStyleConfig[],
    additions: AdjustElementStyleConfig[],
  ): AdjustElementStyleConfig[] {
    const styleMap = new Map<string, AdjustElementStyleConfig>()

    // 添加基础样式
    base.forEach((style) => {
      const key = `${style.selector}_${style.property}`
      styleMap.set(key, style)
    })

    // 合并新增样式（覆盖重复项）
    additions.forEach((style) => {
      const key = `${style.selector}_${style.property}`
      styleMap.set(key, style)
    })

    return Array.from(styleMap.values())
  }

  /**
   * 更新预览
   */
  private updatePreviewUI(source: DataChangeType) {
    const $editPreview = this.getElement('editPreview')
    if ($editPreview) {
      this.components.module.previewConfig.updateUI(this.savedStyles, source, this.components.module.elementStylePicker.getElementSelector())
    }
  }

  /**
   * 处理编辑步骤状态
   */
  private handleEditStepStatus(type: EditType, skip: boolean = false) {
    const stepIndexMap = {
      [EDIT_TYPE_CONFIG.SELECT_ELEMENT]: 0,
      [EDIT_TYPE_CONFIG.SELECT_STYLE]: 1,
      [EDIT_TYPE_CONFIG.ADD]: 2,
      [EDIT_TYPE_CONFIG.QUICK]: 2,
      [EDIT_TYPE_CONFIG.GENERATE]: 3,
      [EDIT_TYPE_CONFIG.OTHER]: 0,
    }

    if (type === EDIT_TYPE_CONFIG.SELECT_ELEMENT && this.components.module.elementStylePicker.selectedStyle) {
      // 如果页面元素选择时，元素样式之前也被选择时，则更新步骤条到元素样式，而不是页面元素
      this.components.base.editStep.setCurrentStep(stepIndexMap[EDIT_TYPE_CONFIG.SELECT_STYLE])
    }
    else {
      this.components.base.editStep.setCurrentStep(stepIndexMap[type] || stepIndexMap[EDIT_TYPE_CONFIG.OTHER])
    }

    if (skip)
      return

    if (!this.components.module.elementStylePicker.selectedElement) {
      this.components.base.editStep.updateStepStatus(stepIndexMap[EDIT_TYPE_CONFIG.SELECT_ELEMENT]!, EDIT_STEP_STATUS.ERROR)
    }
    if (!this.components.module.elementStylePicker.selectedStyle) {
      this.components.base.editStep.updateStepStatus(stepIndexMap[EDIT_TYPE_CONFIG.SELECT_STYLE]!, EDIT_STEP_STATUS.ERROR)
    }
  }

  /**
   * 处理元素选择
   */
  private handleElementStyleSelect = (_selector: selectedType, _group: selectedType) => {
  }

  /**
   * 处理预设选择
   */
  private handlePresetSelect = (preset: string) => {
    this.eventEmitter.emit(CUSTOM_EVENTS.EDIT_STEP, EDIT_TYPE_CONFIG.QUICK)

    if (!preset.includes(':')) {
      logger.warn('无效的预设格式:', preset)
      return
    }

    const [property, value] = preset.split(':').map(s => s.trim())

    this.loadLatestStyles('quick', [this.getElementStyleConfigBase(property, value)])
  }

  /**
   * 重置
   */
  reset(): void {
  }

  getStyles(): string {
    return this.styles()
  }

  /**
   * 获取所有模块分类（module）的组件样式
   */
  getComponentStyles(): string {
    let styles = ''

    Object.values(this.components.module).forEach((component) => {
      try {
        const componentStyles = 'styles' in component ? component.styles() : ''
        if (componentStyles && componentStyles.trim()) {
          styles += `\n/* ${component.constructor.name} Styles */\n${componentStyles}\n`
        }
      }
      catch (error: any) {
        logger.error(`[${this.name}] 获取组件样式失败: ${component.constructor.name}`, error)
      }
    })

    return styles
  }

  /**
   * 组件样式
   */
  styles(): string {
    return `
      /* 子组件样式 */
      ${this.getComponentStyles()}

      /* 主容器样式 */
      .style-editor {
        display: grid;
        grid-template-areas:
          "menu menu"
          "step step"
          "selector selector"
          "toolbar toolbar"
          "edit edit"
          "actions actions"
          "preview preview";
        gap: 15px;
        width: 100%;
        margin: 0 auto;
        border-radius: 8px;
        position: relative;
      }
      
      .editor-menu {
        grid-area: menu;
        display: flex;
        justify-content: space-between;
        align-items: center;
        
        .menu-left {
          display: flex;
          gap: 8px;
        }
        
        .menu-right {
          display: flex;
          gap: 12px;
          align-items: center;
          .focus-mode {
            order: 1; // 确保在最右侧
            position: relative;
            display: flex;
            align-items: center;
            justify-content: right;
          }
        }
      }
      
      .editor-step {
        grid-area: step;
      }
      
      .editor-content {
        grid-column: 1 / -1; /* 跨所有列 */
        width: 100%;
      }

      .editor-selector {
        grid-area: selector;
        border-radius: 6px;
        padding: 10px;
      }
  
      .edit-area {
        grid-area: edit;
        min-height: 100px;
        background: #f8f9fa;
        border-radius: 6px;
        padding: 15px;
        
        .edit-skeleton {
          --skeleton-base: #f0f0f0;
          --skeleton-highlight: #e8e8e8;
        
          display: flex;
          flex-direction: column;
          gap: 15px;
          
          .skeleton-row {
            display: flex;
            align-items: center;
            gap: 10px;
            
            .skeleton-label {
              width: 80px;
              height: 32px;
              background: var(--skeleton-base);
              border-radius: 4px;
              position: relative;
              overflow: hidden;
              &::after {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: linear-gradient(
                  90deg,
                  transparent,
                  var(--skeleton-highlight),
                  transparent
                );
                animation: skeletonShimmer  2s infinite;
              }
            }
            
            .skeleton-input {
              flex: 1;
              height: 32px;
              background: var(--skeleton-base);
              border-radius: 4px;
              position: relative;
              overflow: hidden;
              &::after {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: linear-gradient(
                  90deg,
                  transparent,
                  var(--skeleton-highlight),
                  transparent
                );
              animation: skeletonShimmer  2s infinite;
              }
            }
          }
        }
        
        .${this.components.module.elementStylePicker.controlsContainerClassName} {
          .${this.components.module.elementStylePicker.controlsClassName} {
            .${this.components.module.elementStylePicker.controlsItemClassName} {
              all: initial;
              position: relative;
              height: 100%;
              display: flex;
              align-items: center;
              justify-content: space-between;
              gap: 5px;
              background-color: #f8f9fa;
              border: 1.5px solid transparent;
              padding: 10px 0 !important;
              label {
                display: inline-block;
                font-size: 15px;
                color: #24292e !important;
                font-weight: 500 !important;
                min-width: 100px;
                white-space: nowrap;
              }
            }
          }
        }
      }

      .edit-actions {
        grid-area: actions;
        margin-top: 10px;
      }

      .edit-preview {
        grid-area: preview;
        background: #e3e3e3;
        border: 1px solid #e0e0e0;
        margin-top: 30px;
        padding: 0;
        border-radius: 8px;
        max-height: 500px;
        overflow-y: auto;
        
        ${StylesService.getInstance().scroll.default}
      }
    `
  }
}
